概述
本文我们来介绍 SystemUI 下拉面板快捷开关的实现原理。
下拉面板中的 QQS 和 QS 分别可以承载 QS Tile ,进行一些快捷设置的功能。
模块划分
- TileView:主要负责快捷开关的视图展示。
- QSTileView:继承自 LinearLayout,实现 QS 视图的抽象类。
- QSTileViewImpl:继承自 QSTileView,
- CustomizeTileView:继承自 QSTileViewImpl,编辑页面中用到
- QSTile:主要负责快捷开关的逻辑处理。
- QSTile
- QSTileImpl
- CustomTile:编辑页面中需要用到
- WifiTile
- BluetoothTile
- State
- BooleanState
- SignalState
- QSHost
- QSHost:主要负责快捷开关TileView和QSTile的构建,提供获取QSTile集合的接口,提供了展开和收起下拉面板的接口,是快捷开关对外沟通的桥梁。
- QSTileHost:
- QSFactory:
- QSFactoryImpl:继承自 QSFactory
- QSPanel:承载快捷开关的容器。
- QuickQSPanel:继承自 QSPanel,显示 QQS 部分快捷开关。
- QSPanel:继承自 LinearLayout,显示 QS 快捷开关。
- QSTileLayout
- TileLayout
- PagedTileLayout
- SideLabelTileLayout
- QS:QS面板的顶层容器,主要处理QS面板的展开/收起逻辑。
- QSContainerImpl:下拉面板快捷开关部分的根布局,包含QQS,QS,QSDetail,QSCustomer 等。添加到 QSFragment。
- QSFragment:包含 QSContainerImpl 的 QSFragment。
- QS:主要定义了 QS 面板展开/收起相关的接口
QS Tile 的创建
创建 QSTile,通过初始化 QsTileHost,进行 QsTile 的加载。在 QsTileHost 初始化的时候,增加 Tunable 监听。
1 | QSTileHost() |
TunerServiceImpl 中注册对字段”sysui_qs_tiles”的系统数据库监听,当编辑模式添加或者删除 Tile 时,会触发重新加载 Tile。
1 | // TunerServiceImpl.java |
根据配置文件生成对应的 QSTile。
1 | // QSFactoryImpl.java |
创建 QSTileView
1 | QSFragment.onViewCreated() |
从上面流程可以看出来,QSTileHost 对象在构建的时候就通过 QSFactoryImpl 创建好了各个开关的对应的 QSTile,而后 QSPanel 在初始化的过程中,再次利用 QSTileHost 去构建各个开关的视图对象 QSTileView。
编辑页面 QS Tile 的创建
进入 QS 编辑模式之后,会出现更多 Tile,并且可以拖动到上方供用户平时下拉后直接使用,或者将不常用的放到待选区域。这里从UI上可以看出待选区域由两部分组成,一部分是 SystemUI 内部的 Tile(StockTiles),另一部分则是第三应用自己注册的 Tile(PackageTiles)。
1 | QSPanelController.showEdit() |
获取 R.string.quick_settings_tiles_stock 对应的就是SystemUI中可加载的所有Tile,如果希望客制化也可以在此处进行修改。
接下来,再看一下如何加载第三方 Tile。
1 | TileQueryHelper.TileCollector.onStateChanged() |
关联 QS Tile 和 QS View
它们关联的建立主要时通过 QSTile.Callback 和 QSTile.State 来实现。
1 | public interface Callback { |
在 QSPanelControllerBase.addTile() 中创建 QSTileView 时调用 QSPanel.addTile() 为它们建立联系:
1 | // QSPanel.java |
下面一次点击事件来介绍一下它们之间的关联。
BluetoothTile 继承自 QSTileImpl,实现了抽象方法 handleClick(),handleUpdateState()
点击事件触发后,先把 State 发送给 QSTileImpl 来更新逻辑,然后再通过回调函数通知 QSTileView 更新 UI。
1 | QSTileViewImpl.onClick() // 在init()方法中注册 |